package com.seed.uaa.web.user;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryChain;
import com.mybatisflex.core.query.QueryWrapper;
import com.seed.application.service.BaseService;
import com.seed.core.pojo.Const;
import com.seed.core.pojo.SetDTO;
import com.seed.uaa.pojo.OrganizationAction;
import com.seed.uaa.pojo.RoleAction;
import com.seed.uaa.pojo.UserAction;
import com.seed.uaa.util.EncryptUtil;
import com.seed.uaa.util.PermiUtil;
import com.seed.uaa.web.UaaService;
import com.seed.uaa.web.organization.Organization;
import com.seed.uaa.web.organization.OrganizationService;
import com.seed.uaa.web.role.Role;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.seed.uaa.web.organization.table.OrganizationTableDef.ORGANIZATION;
import static com.seed.uaa.web.role.table.RoleTableDef.ROLE;
import static com.seed.uaa.web.user.table.UserRoleTableDef.USER_ROLE;
import static com.seed.uaa.web.user.table.UserTableDef.USER;

@Service
public class UserService extends BaseService<UserMapper, User> {

    private final OrganizationService organizationService;
    public UserService(@Lazy UaaService uaaService, OrganizationService organizationService) {
        super(User.class);
        this.organizationService = organizationService;
    }

//    public boolean setUsername(User value) {
//        String id = value.getId();
//        String username = value.getUsername();
//
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//        if(username.equals(user.getUsername())) return true;
//
//        List<User> users = list(query().where(UserTableDef.USER.USERNAME.eq(username)).and(UserTableDef.USER.ID.ne(id)));
//        if(!users.isEmpty()) {
//            throw new RuntimeException(String.format("账号【%s】已存在", username));
//        }
//
//        String rawPassword = "123456";
//        String salt = UUID.fastUUID().toString();
//        String encrypt = EncryptUtil.encrypt(rawPassword, salt);
//        return UpdateChain.of(User.class)
//                .set(User::getUsername, username)
//                .set(User::getPassword, encrypt)
//                .set(User::getSalt, salt)
//                .where(UserTableDef.USER.ID.eq(id))
//                .update();
//    }

    public boolean resetPassword(String id) {
        User user = getById(id);
        if(user == null) throw new RuntimeException("数据不存在");

        String salt = UUID.fastUUID().toString();
        String encrypt = EncryptUtil.encrypt(Const.INIT_PASSWORD_VALUE, salt);
        user.setPassword(encrypt);
        user.setSalt(salt);
        return update(user);
    }

//    @Override
//    public boolean reset(String id) {
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//
//        String rawPassword = "123456";
//        String salt = UUID.fastUUID().toString();
//        String encrypt = EncryptUtil.encrypt(rawPassword, salt);
//        return UpdateChain.of(User.class)
//                .set(User::getPassword, encrypt)
//                .set(User::getSalt, salt)
//                .where(USER.ID.eq(id))
//                .update();
//    }

//    @Override
//    public boolean setExpireDate(String id, String value) {
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//        LocalDateTime expireDate = StrUtil.isBlank(value) ? null : DateUtil.parseLocalDateTime(value + " 23:59:59");
//        return UpdateChain.of(User.class)
//                .set(User::getExpireDate, expireDate)
//                .where(USER.ID.eq(id))
//                .update();
//    }
//
//    @Override
//    public boolean setUsable(String id, YesNo value, String reason) {
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//
//        return UpdateChain.of(User.class)
//                .set(User::getUsable, value)
//                .set(User::getReason, reason)
//                .where(USER.ID.eq(id))
//                .update();
//    }
//
//    @Override
//    public boolean setLoginable(String id, YesNo value, String reason) {
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//
//        return UpdateChain.of(User.class)
//                .set(User::getLoginable, value)
//                .set(User::getReason, reason)
//                .where(USER.ID.eq(id))
//                .update();
//    }
//
//    @Override
//    public boolean setEnable(String id, YesNo value, String reason) {
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//
//        return UpdateChain.of(User.class)
//                .set(User::getEnable, value)
//                .set(User::getReason, reason)
//                .where(USER.ID.eq(id))
//                .update();
//    }
//
//    @Override
//    public boolean active(String id) {
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//        if(YesNo.yes.equals(user.getActive())) return true;
//
//        return UpdateChain.of(User.class)
//                .set(User::getActive, YesNo.yes)
//                .where(USER.ID.eq(id))
//                .update();
//    }

//    public List<String> getRoles(String id) {
//        QueryWrapper qw = query().where(USER_ROLE.USER_ID.eq(id));
//        return userRoleMapper.selectListByQuery(qw).stream().map(UserRole::getRoleId).toList();
//    }
//
//    @Override
//    @Transactional
//    public boolean setRoles(String id, String value) {
//        User user = getById(id);
//        if(user == null) throw new RuntimeException("数据不存在");
//
//        UpdateChain.of(UserRole.class).where(USER_ROLE.USER_ID.eq(id)).remove();
//        if(StrUtil.isNotBlank(value)) {
//            List<UserRole> userRoles = Stream.of(value.split(","))
//                    .map(roleId -> {
//                        UserRole ret = new UserRole();
//                        ret.setUserId(id);
//                        ret.setRoleId(roleId.trim());
//                        return ret;
//                    }).toList();
//            userRoleMapper.insertBatch(userRoles);
//        }
//        return true;
//    }

    public boolean setActions(SetDTO dto) {
        String id = dto.getId();
        User user = one(id);
        if(user == null) throw new RuntimeException("数据不存在");

        String value = dto.getValue();
        user.setActions(value);
        return getMapper().update(user) > 0;
    }

    public boolean setDatas(String id, String actionPath, List<String> params) {
        QueryWrapper queryWrapper = query()
                .select(USER.ID, USER.DATAS, USER.VERSION)
                .where(USER.ID.eq(id));

        User user = getMapper().selectOneByQuery(queryWrapper);
        if(user == null) throw new RuntimeException("数据不存在");

        user.setDatas(PermiUtil.edit(user.getDatas(), actionPath, params));
        return getMapper().update(user) > 0;
    }

    public boolean setFields(String id, String actionPath, Map<String, String> params) {
        QueryWrapper queryWrapper = query()
                .select(USER.ID, USER.FIELDS, USER.VERSION)
                .where(USER.ID.eq(id));

        User user = getMapper().selectOneByQuery(queryWrapper);
        if(user == null) throw new RuntimeException("数据不存在");

        user.setFields(PermiUtil.edit(user.getFields(), actionPath, params));
        return getMapper().update(user) > 0;
    }

    private User one(String id) {
        QueryWrapper queryWrapper = query()
                .select(USER.ID, USER.VERSION)
                .where(USER.ID.eq(id));
        return getMapper().selectOneByQuery(queryWrapper);
    }

    /**
     * 我自己的权限
     */
    public List<String> getActions(String id) {
        QueryWrapper queryWrapper = query()
                .select(USER.ID, USER.ACTIONS)
                .where(USER.ID.eq(id));

        User user = getMapper().selectOneByQuery(queryWrapper);
        if(user == null) throw new RuntimeException("数据不存在");

        String actions = user.getActions();
        if(StrUtil.isBlank(actions)) return Collections.emptyList();

        return List.of(actions.split(","));
    }

    /**
     * 我拥有的权限，包含我自己的权限和角色的权限，用or连接
     * @param id 用户ID
     * @return
     */
    public List<String> getHaveActions(String id) {
        List<String> ret = new ArrayList<>(getActions(id));

        List<Role> roles = QueryChain.of(Role.class)
            .select(ROLE.ID, ROLE.ACTIONS)
            .innerJoin(USER_ROLE).on(USER_ROLE.USER_ID.eq(id))
            .list();

        for(Role role: roles) {
            String actions = role.getActions();
            if(StrUtil.isNotBlank(actions)) {
                ret.addAll(List.of(actions.split(",")));
            }
        }

        return ret.stream().distinct().toList();
    }

    /**
     * 我最终的权限：我拥有的权限和我所有职位拥有的权限的合并，用or连接
     * @param id 用户ID
     */
    public List<String> getFinalActions(String id) {
        List<String> ret = new ArrayList<>(getHaveActions(id));
        // 查找用户负责的职位
        List<Organization> positions = QueryChain.of(Organization.class)
                .select(ORGANIZATION.ID)
                .where(ORGANIZATION.MANAGER_ID.eq(id))
                .list();
        for(Organization position: positions) {
            List<String> actions = organizationService.getHaveActions(position.getId());
            ret.addAll(actions);
        }

        return ret.stream().distinct().toList();
    }

    /**
     * 我自己权限
     */
    public List<String> getDatas(String id, String actionPath) {
        QueryWrapper queryWrapper = query()
                .select(USER.ID, USER.DATAS)
                .where(USER.ID.eq(id));

        User user = getMapper().selectOneByQuery(queryWrapper);
        if(user == null) throw new RuntimeException("数据不存在");

        String datas = user.getDatas();
        if(StrUtil.isBlank(datas)) return Collections.emptyList();

        return PermiUtil.extract(datas, actionPath);
    }

    /**
     * 我拥有的权限：包含我自己的权限和角色的权限, 用or连接
     */
    public List<List<String>> getHaveDatas(String id, String actionPath) {
        List<String> selfDatas = getDatas(id, actionPath);
        List<Role> roles = QueryChain.of(Role.class)
            .select(ROLE.ID, ROLE.DATAS)
            .innerJoin(USER_ROLE).on(USER_ROLE.USER_ID.eq(id))
            .list();

        List<List<String>> ret = new ArrayList<>();
        ret.add(selfDatas);
        for(Role role: roles) {
            String datas = role.getDatas();
            if(StrUtil.isNotBlank(datas)) {
                ret.add(PermiUtil.extract(datas, actionPath));
            }
        }

        return ret;
    }

    /**
     * 我最终的权限：包含我拥有的权限和职位拥有的权限, 用or连接
     * @param id
     * @return
     */
    public List<List<String>> getFinalDatas(String id, String actionPath) {
        List<List<String>> ret = new ArrayList<>();
        List<List<String>> haveDatas = getHaveDatas(id, actionPath);
        List<List<String>> organizationHaveDatas = organizationService.getHaveDatas(id, actionPath);

        ret.addAll(haveDatas);
        ret.addAll(organizationHaveDatas);

        return ret;
    }

    // 我自己的权限
    public Map<String, String> getFields(String id, String actionPath) {
        QueryWrapper queryWrapper = query()
                .select(USER.ID, USER.FIELDS)
                .where(USER.ID.eq(id));

        User user = getMapper().selectOneByQuery(queryWrapper);
        if(user == null) throw new RuntimeException("数据不存在");

        String fields = user.getFields();
        if(StrUtil.isBlank(fields)) return Collections.emptyMap();

        Map<String, String> ret = new HashMap<>();
        PermiUtil.fillFields(ret, fields, actionPath);

        return ret;
    }

    /**
     * 我拥有的权限：包含我自己的权限和角色的权限, 用or连接
     */
    public Map<String, String> getHaveFields(String id, String actionPath) {
        Map<String, String> ret = getFields(id, actionPath);

        List<Role> roles = QueryChain.of(Role.class)
            .select(ROLE.ID, ROLE.FIELDS)
            .innerJoin(USER_ROLE).on(USER_ROLE.USER_ID.eq(id))
            .list();

        for(Role role: roles) {
            String fields = role.getFields();
            if(StrUtil.isBlank(fields)) {
                PermiUtil.fillFields(ret, fields, actionPath);
            }
        }

        return ret;
    }

    /**
     * 我最终的权限：包含我拥有的权限和职位的权限, 用or连接
     */
    public Map<String, String> getFinalFields(String id, String actionPath) {
        Map<String, String> ret = getHaveFields(id, actionPath);
        // 查找用户负责的职位
        List<Organization> positions = QueryChain.of(Organization.class)
                .select(ORGANIZATION.ID)
                .where(ORGANIZATION.MANAGER_ID.eq(id))
                .list();
        for(Organization position: positions) {
            Map<String, String> fields = organizationService.getHaveFields(position.getId(), actionPath);
            for(Map.Entry<String, String> entry: fields.entrySet()) {
                ret.putIfAbsent(entry.getKey(), entry.getValue());
            }
        }

        return ret;
    }

    public UserAction getUserAction(String id) {
        User user = QueryChain.of(User.class)
                .select(USER.ID, USER.NAME, USER.ACTIONS)
                .where(USER.ID.eq(id))
                .one();
        if(user == null) throw new RuntimeException("数据不存在");

        UserAction ret = new UserAction(user.getId(), user.getName());
        String actions = user.getActions();
        if(StrUtil.isNotBlank(actions)) {
            ret.setActions(List.of(actions.split(",")));
        }

//        String organizationId = user.getOrganizationId();
//        if(StrUtil.isNotBlank(organizationId)) {
//            ret.setOrganizationAction(getOrganizationAction(organizationId));
//        }
        List<RoleAction> roleActions = new ArrayList<>();
        List<Role> roles = QueryChain.of(Role.class)
                .select(ROLE.ID, ROLE.NAME)
                .innerJoin(USER_ROLE).on(USER_ROLE.USER_ID.eq(user.getId()))
                .list();

        for(Role role: roles) {
            RoleAction roleAction = new RoleAction(role.getId(), role.getName());
            String actions1 = role.getActions();
            if(StrUtil.isNotBlank(actions1)) {
                roleAction.setActions(List.of(actions1.split(",")));
                roleActions.add(roleAction);
            }
        }
        ret.setRoleActions(roleActions);

        List<OrganizationAction> positionActions = new ArrayList<>();
        List<Organization> positions = QueryChain.of(Organization.class)
                .select(ORGANIZATION.ID, ORGANIZATION.NAME, ORGANIZATION.CODE)
                .where(ORGANIZATION.MANAGER_ID.eq(id))
                .list();
        for(Organization position: positions) {
            positionActions.add(organizationService.getOrganizationAction(position.getId()));
        }

        ret.setPositionActions(positionActions);

        return ret;
    }

    private List<RoleAction> userRoleSelfAction(User user) {
        List<RoleAction> roleActions = new ArrayList<>();
        List<Role> roles = QueryChain.of(Role.class)
                .select(ROLE.ID, ROLE.NAME)
                .innerJoin(USER_ROLE).on(USER_ROLE.USER_ID.eq(user.getId()))
                .list();

        for(Role role: roles) {
            RoleAction roleAction = new RoleAction(role.getId(), role.getName());
            String actions = role.getActions();
            if(StrUtil.isNotBlank(actions)) {
                roleAction.setActions(List.of(actions.split(",")));
                roleActions.add(roleAction);
            }
        }

        return roleActions;
    }
}
